package cn.bs.seckill.service.impl;

import cn.bs.seckill.exception.GlobalException;
import cn.bs.seckill.pojo.Orders;
import cn.bs.seckill.mapper.OrdersMapper;
import cn.bs.seckill.pojo.SeckillGoods;
import cn.bs.seckill.pojo.SeckillOrders;
import cn.bs.seckill.pojo.User;
import cn.bs.seckill.service.GoodsService;
import cn.bs.seckill.service.OrdersService;
import cn.bs.seckill.service.SeckillGoodsService;
import cn.bs.seckill.service.SeckillOrdersService;
import cn.bs.seckill.utils.MD5Util;
import cn.bs.seckill.utils.RedisUtil;
import cn.bs.seckill.utils.UUIDUtil;
import cn.bs.seckill.vo.DetailVo;
import cn.bs.seckill.vo.GoodsVo;
import cn.bs.seckill.vo.RespBeanEnum;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.concurrent.TimeUnit;

/**
 * <p>
 * 秒杀实现类
 * </p>
 *
 * @author 布索
 * @since 2022-03-01
 */
@Service
public class OrdersServiceImpl extends ServiceImpl<OrdersMapper, Orders> implements OrdersService {

    @Autowired
    private SeckillGoodsService seckillGoodsService;

    @Autowired
    private OrdersMapper ordersMapper;

    @Autowired
    private GoodsService goodsService;
    @Autowired
    private SeckillOrdersService seckillOrdersService;
    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private RedisUtil redisUtil;
    @Transactional
    @Override
    public Orders secKill(User user, GoodsVo goods) {

        //通过商品id拿到对应的秒杀商品
        SeckillGoods seckillGoods = seckillGoodsService.getOne(new QueryWrapper<SeckillGoods>().eq("goods_id", goods.getId()));
        //对应秒杀商品的库存减一
        seckillGoods.setStockCount(seckillGoods.getStockCount() - 1);
        //通过商品id查到商品,再把对应商品的的库存变成减了过后的库存,再判断库存是否大于等于0,最后再更新
        boolean update = seckillGoodsService.update(new UpdateWrapper<SeckillGoods>().eq("goods_id", goods.getId()).setSql("stock_count=" + "stock_count-1").gt("stock_count", 0));
        //如果更新失败,就不做操作了
       /* if (!update) {
            return null;
        }*/

        if (seckillGoods.getStockCount() < 1) {
            //判断是否还有库存
            redisUtil.set("isStockEmpty:" + goods.getId(), "0");
            return null;
        }
        Orders order = new Orders();
        //设置相应的值,因为前端很简陋,并没有相应的数据传入后端,所以这里就手动赋值写死
        order.setUserId(user.getId());
        order.setGoodsId(goods.getId());
        order.setDeliveryAddrId(0L);
        order.setGoodsName(goods.getGoodsName());
        order.setGoodsCount(1);
        order.setGoodsPrice(seckillGoods.getSeckillPrice());
        order.setGoodsChannel(1);
        order.setStatus(0);
        order.setCreateDate(LocalDateTime.now());
        ordersMapper.insert(order);
        //生成秒杀订单
        SeckillOrders seckillOrders = new SeckillOrders();
        seckillOrders.setUserId(user.getId());
        seckillOrders.setOrderId(order.getId());
        seckillOrders.setGoodsId(goods.getId());
        seckillOrdersService.save(seckillOrders);
        redisUtil.set("order:"+user.getId()+":"+goods.getId(),seckillOrders);
        return order;


    }

    @Override
    public DetailVo detail(Long orderId) {

        if (null==orderId){
            throw new GlobalException(RespBeanEnum.NO_ORDER_MESSAGE);
        }
        Orders order = ordersMapper.selectById(orderId);
        //通过id获取商品
        GoodsVo goodsVo = goodsService.findGoodsVoByGoodsId(order.getGoodsId());
        DetailVo detail = new DetailVo();
        detail.setGoodsVo(goodsVo);
        detail.setOrders(order);
        return detail;

    }

    //获取秒杀地址
    @Override
    public String createPath(User user, Long goodsId) {
        String str = MD5Util.md5(UUIDUtil.uuid() + "123456");
        redisTemplate.opsForValue().set("seckillPath:" + user.getId() + ":" + goodsId, str, 60, TimeUnit.SECONDS);
        return str;
    }

    //校验秒杀地址
    @Override
    public Boolean checkPath(User user,Long goodsId,String path) {
        String key = "seckillPath:" + user.getId() + ":" + goodsId;
        String rightPath = (String) redisTemplate.opsForValue().get(key);
        if(rightPath == null || !rightPath.equals(path)) {
            return false;
        }
        return true;
    }

    //校验验证码
    @Override
    public Boolean checkCptcha(User user, Long goodsId, String captcha) {
        if(StringUtils.isEmpty(captcha) || user == null || goodsId < 0) {
            return false;
        }
        String rightCaptcha = (String) redisTemplate.opsForValue().get("captcha:" + user.getId() + ":" + goodsId);
        if(!captcha.equals(rightCaptcha)) {
            return false;
        }
        return true;
    }
}
